﻿using System;
using System.Collections.Generic;
using System.Text;
using Vortex;
using Vortex.Drawing;
using Vortex.Input;

namespace Vortex.Tutorials.DrawingTransformations {

    ///<summary>This tutorial shows geometry transformations supported with Vortex2D</summary>
    class DrawingTransformations : Game {
        readonly static string HELP_TEXT = "Translate - Left, Right, Up, Down\nRotate - A, D\nScale - W, S\nReset - R\n\nExit - Esc";

        const float TRANSLATION_SPEED = 180.0f;
        const float SCALING_SPEED = 0.8f;
        const float ROTATION_SPEED = 0.9f;
        readonly Vector2 TRANSLATION_LOW_BOUND = new Vector2(0, 0);
        readonly Vector2 TRANSLATION_HIGH_BOUND = new Vector2(800, 600);

        Texture _FlowerTexture;
        SpriteFont _CorridaFont;

        Translation _CardTranslation;
        Rotation _CardRotation;
        Scaling _CardScaling;

        Vector2 _TranslationSpeed;
        float _RotationSpeed;
        float _ScalingSpeed;

        public DrawingTransformations() {
            Window.Size = new System.Drawing.Size(800, 600);
            SetTransformationDefaults();
        }

        private void SetTransformationDefaults () {
            _CardTranslation = new Translation(400, 300);
            _CardScaling = Scaling.Empty;
            _CardRotation = Rotation.Empty;
        }

        protected override void Load () {
            _FlowerTexture = new Texture(@"{graphics}\flower.jpg");
            _CorridaFont = new SpriteFont(@"{fonts}\CorridaC, 48px");

            //using allmighty power of delegates to create inline handler on exit
            Keyboard.KeyUp += delegate(VirtualKey key) {
                if (key == VirtualKey.Escape) {
                    Terminate();
                }
            };
        }

        protected override void Unload () {
            _FlowerTexture.Dispose();
        }

        protected override void Update (GameTime time) {
            //Process rotation machanics
            float rotationSpeed = 0.0f;

            if (Keyboard.IsDown(Key.A)) rotationSpeed -= ROTATION_SPEED;
            if (Keyboard.IsDown(Key.D)) rotationSpeed += ROTATION_SPEED;

            if (rotationSpeed != 0) {
                _RotationSpeed = rotationSpeed;
            } else {
                _RotationSpeed = _RotationSpeed * (1.0f - time.FrameTime * 4);
            }

            //Process movement mechanics
            Vector2 translationSpeed = Vector2.Zero;

            if (Keyboard.IsDown(Key.Left)) translationSpeed.X -= TRANSLATION_SPEED;
            if (Keyboard.IsDown(Key.Right)) translationSpeed.X += TRANSLATION_SPEED;
            if (Keyboard.IsDown(Key.Up)) translationSpeed.Y -= TRANSLATION_SPEED;
            if (Keyboard.IsDown(Key.Down)) translationSpeed.Y += TRANSLATION_SPEED;

            if (!translationSpeed.IsEmpty) {
                _TranslationSpeed = translationSpeed;
            } else {
                _TranslationSpeed = _TranslationSpeed * (1.0f - time.FrameTime * 4);
            }

            //Process scaling mechanics
            float scalingSpeed = 0.0f;

            if (Keyboard.IsDown(Key.S)) scalingSpeed -= SCALING_SPEED;
            if (Keyboard.IsDown(Key.W)) scalingSpeed += SCALING_SPEED;

            if (scalingSpeed != 0.0f) {
                _ScalingSpeed = scalingSpeed;
            } else {
                _ScalingSpeed = _ScalingSpeed * (1.0f - time.FrameTime * 4);
            }

            //Check for reset
            if (Keyboard.IsPressed(Key.R)) {
                SetTransformationDefaults();
            }


            //update transformations
            //translation is bounded; card center should be in screen space
            _CardTranslation.Offset = (_CardTranslation.Offset + _TranslationSpeed * time.FrameTime).Max(TRANSLATION_LOW_BOUND).Min(TRANSLATION_HIGH_BOUND);
            _CardRotation.Angle += _RotationSpeed * time.FrameTime;
            //scaling should be at least 0.05
            _CardScaling.Factor = (_CardScaling.Factor + _ScalingSpeed * time.FrameTime).Max(new Vector2(0.05f));

        }

        protected override void Render (Canvas2D canvas) {
            canvas.Clear(ColorU.Gray);

            //applying multiple transformations to canvas for specified scope
            using (canvas <= _CardTranslation <= _CardRotation <= _CardScaling) {
                //all drawn inside of this scope will be transformed:

                canvas.DrawSprite(0, 0, _FlowerTexture.ToSprite(), ColorU.White);
                canvas.DrawText(_CorridaFont, new Vector2(30, 190), "Flowers,\nThey are so beautiful...", ColorU.White);
				canvas.DrawRect(new Rect(canvas.Region.Center.Negative, canvas.Region.Center), ColorU.Yellow);
            }

            canvas.DrawTextLayout(SpriteFont.Console, canvas.Region.Deflate(new Vector2(4, 4)), HELP_TEXT, TextLayout.Left | TextLayout.Bottom, ColorU.Black);
        }
    }
}
